﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Data;
using StyleMVVM.DependencyInjection;
using StyleMVVM.Logging;

namespace StyleMVVM.ViewModel
{
	public class CustomDataModelViewModelPropertyInfo : PropertyInfo
	{
		private static string supplemental = typeof(CustomDataModelViewModelPropertyInfo).FullName;

		private Type viewModelType;
		private string propertyName;
		private Type propertyType;
		private bool canWrite;
		private MethodInfo getMethodInfo;
		private MethodInfo setMethodInfo;

		public CustomDataModelViewModelPropertyInfo(Type viewModelType, string propertyName, Type propertyType, bool canWrite)
		{
			this.viewModelType = viewModelType;
			this.propertyName = propertyName;
			this.propertyType = propertyType;
			this.canWrite = canWrite;

			getMethodInfo = viewModelType.GetMethod("GetModelPropertyValue");

			if (canWrite)
			{
				setMethodInfo = viewModelType.GetMethod("SetModelPropertyValue");
			}
		}

		public override object[] GetCustomAttributes(bool inherit)
		{
			return new Attribute[] { };
		}

		public override bool IsDefined(Type attributeType, bool inherit)
		{
			return false;
		}

		public override object GetValue(object obj,
		                                BindingFlags invokeAttr,
		                                Binder binder,
		                                object[] index,
		                                CultureInfo culture)
		{
			return getMethodInfo.Invoke(obj, new object[] { Name });
		}

		public override void SetValue(object obj,
		                              object value,
		                              BindingFlags invokeAttr,
		                              Binder binder,
		                              object[] index,
		                              CultureInfo culture)
		{
			setMethodInfo.Invoke(obj, new object[] { Name, value });
		}

		public override MethodInfo[] GetAccessors(bool nonPublic)
		{
			throw new NotImplementedException();
		}

		public override MethodInfo GetGetMethod(bool nonPublic)
		{
			return getMethodInfo;
		}

		public override MethodInfo GetSetMethod(bool nonPublic)
		{
			if (canWrite)
			{
				return setMethodInfo;
			}

			throw new NotImplementedException();
		}

		public override ParameterInfo[] GetIndexParameters()
		{
			return new ParameterInfo[] { };
		}

		public override string Name
		{
			get { return propertyName; }
		}

		public override Type DeclaringType
		{
			get { return viewModelType; }
		}

		public override Type ReflectedType
		{
			get { throw new NotImplementedException(); }
		}

		public override Type PropertyType
		{
			get { return propertyType; }
		}

		public override PropertyAttributes Attributes
		{
			get { return new PropertyAttributes(); }
		}

		public override bool CanRead
		{
			get { return true; }
		}

		public override bool CanWrite
		{
			get { return canWrite; }
		}

		public override object[] GetCustomAttributes(Type attributeType, bool inherit)
		{
			return new Attribute[] { };
		}
	}
}